home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / human interface toolbox / noresdialog / noresdialog.c next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  27.1 KB  |  704 lines

  1. /*
  2.     File:        NoResDialog.c
  3.  
  4.     Contains:   OK, so despite all your planning, you still think you may need to
  5.                 create dialogs on the fly , without having any resource templates
  6.                     available for the DITL.
  7.     
  8.                 Pain in the butt.  The Dialog Manager was not designed for not using resources, so
  9.                 you'll be abusing a manager again to do so (hehehehe).
  10.                 But doable, and actually not that much of a pain once you have some basic information.
  11.  
  12.                 This small sample shows how, it creates a dialog with an OK button witha border
  13.                 around it all with in-memory data structures, no resources used.
  14.  
  15.                 Just look at the function NoResDialog(...), and you'll see.
  16.  
  17.     Written by: C.K. Haun     
  18.  
  19.     Copyright:    Copyright © 1991-1999 by Apple Computer, Inc., All Rights Reserved.
  20.  
  21.                 You may incorporate this Apple sample source code into your program(s) without
  22.                 restriction. This Apple sample source code has been provided "AS IS" and the
  23.                 responsibility for its operation is yours. You are not permitted to redistribute
  24.                 this Apple sample source code as "Apple sample source code" after having made
  25.                 changes. If you're going to re-distribute the source, we require that you make
  26.                 it clear in the source that the code was descended from Apple sample source
  27.                 code, but that you've made changes.
  28.  
  29.     Change History (most recent first):
  30.                 8/9/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  31.                 
  32.  
  33. */
  34.  
  35.  
  36. #include <Dialogs.h>
  37. #include <Fonts.h>
  38. #include <Menus.h>
  39. #include <AppleEvents.h>
  40. #include <Resources.h>
  41. #include <SegLoad.h>
  42. #include <TextUtils.h>
  43. #include "NoResDialog.h"
  44.  
  45. /* prototypes */
  46.  
  47. void InitalizeApp(void);
  48. void DoDiskEvents(long dinfo);                              /* hi word is error code, lo word is drive number */
  49. void DrawMain(WindowPtr drawIt);
  50. Boolean DoSelected(long val);
  51. void SizeMain(WindowPtr theWindow, short how);
  52. void InitAEStuff(void);
  53. void DoHighLevel(EventRecord *AERecord);
  54. void DoDaCall(MenuHandle themenu, long theit);
  55. void DoDocumentClick(WindowPtr theWindow, EventRecord *theEvent);
  56.  
  57. pascal OSErr AEOpenHandler(const AppleEvent *messagein, AppleEvent *reply, unsigned long refIn);
  58. pascal OSErr AEOpenDocHandler(const AppleEvent *messagein, AppleEvent *reply, unsigned long refIn);
  59. pascal OSErr AEPrintHandler(const AppleEvent *messagein, AppleEvent *reply, unsigned long refIn);
  60. pascal OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, unsigned long refIn);
  61.  
  62. void SampleHelpDialog(void);
  63.  
  64. WindowPtr AddNewWindow(short theID);
  65.  
  66. void NilProc(void);
  67. /* one external */
  68. #ifdef applec
  69.     extern void _DataInit();                                    /* this is the C initialization code */
  70. #endif
  71.  
  72. /* globals */
  73. Boolean gQuit, gInBackground;
  74. unsigned long gMySleep;
  75. ProcessSerialNumber gOurSN;
  76. short gHelpItem;
  77.  
  78. void NoResDialog(void);
  79. pascal void BorderDefault(DialogPtr dwind, short dinum);
  80.  
  81.  
  82. #pragma segment Main
  83. void main()
  84. {
  85.     EventRecord myEventRecord;
  86.     WindowPtr twindow;
  87.     short fHit;
  88.     windowCHandle tempWCH;
  89.     
  90.     #ifdef applec
  91.         UnloadSeg((Ptr)_DataInit);                              /* throw out setup code */
  92.     #endif
  93.     
  94.     InitalizeApp();
  95.     UnloadSeg((Ptr)InitalizeApp);                           /* get rid of my initialization code */
  96.     do {
  97.         WaitNextEvent(everyEvent, &myEventRecord, gMySleep, nil);
  98.         switch (myEventRecord.what) {
  99.             case nullEvent:
  100.                 
  101.                 /* no nul processing in this sample */
  102.                 break;
  103.             case updateEvt:
  104.                 /* always check to see if it's my window */
  105.                 /* this may not seem necessary under 7.0, where it's unlikely or impossible for */
  106.                 /* a DA to be in your layer, but there are others  */
  107.                 /* who can stick themselves into your window list, */
  108.                 /* BalloonWriter comes quickly to mind */
  109.                 if (((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow) {
  110.                     tempWCH = (windowCHandle)GetWRefCon((WindowPtr)myEventRecord.message);
  111.                     ((*tempWCH)->drawMe)((WindowPtr)myEventRecord.message);
  112.                 }
  113.                 break;
  114.             case mouseDown:
  115.                 /* first see where the hit was */
  116.                 fHit = FindWindow(myEventRecord.where, &twindow);
  117.                 switch (fHit) {
  118.                     Rect limitRect;
  119.                     Str255 tempString;
  120.                     long back;
  121.                     case inDesk:                            /* if they hit in desk, then the process manager */
  122.                         break;                              /* will switch us out, we don't need to do anything */
  123.                     case inMenuBar:
  124.                         DoSelected(MenuSelect(myEventRecord.where));
  125.                         break;
  126.                         
  127.                     case inSysWindow:
  128.                         /* pass to the system */
  129.                         SystemClick(&myEventRecord, twindow);
  130.                         break;
  131.                     case inContent:
  132.                         /* Handle content and control clicks here */
  133.                         if (((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow) { /* don't do this unless we have a window open, silly */
  134.                             windowCHandle clicker;
  135.                             clicker = (windowCHandle)GetWRefCon(twindow);
  136.                             /* jump to the content function stored for this window */
  137.                             HLock((Handle)clicker);         /* lock it down so things don't get stupid */
  138.                             ((*clicker)->clickMe)(twindow, &myEventRecord);
  139.                             HUnlock((Handle)clicker);       /* all done */
  140.                         }
  141.                         break;
  142.                     case inDrag:
  143.                         DragWindow(twindow, myEventRecord.where, &qd.screenBits.bounds);
  144.                         break;
  145.                     case inGrow:
  146.                         /* Call GrowWindow here if you have a grow box */
  147.                         SetPort(twindow);
  148.                         limitRect = qd.screenBits.bounds;
  149.                         limitRect.top = kMinHeight;
  150.                         GetWTitle(twindow, tempString);
  151.                         /* I'm not letting the user shrink the window so */
  152.                         /* small that the title is truncated */
  153.                         limitRect.left = StringWidth(tempString) + 120;
  154.                         back = GrowWindow(twindow, myEventRecord.where, &limitRect);
  155.                         
  156.                         if (back) {
  157.                             if (((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow) {
  158.                                 windowCHandle tempWCH = (windowCHandle)GetWRefCon(twindow);
  159.                                 Rect sizeRect = ((WindowPtr)twindow)->portRect;
  160.                                 InvalRect(&sizeRect);
  161.                                 sizeRect.top = sizeRect.bottom - 16;
  162.                                 sizeRect.left = sizeRect.right - 16;
  163.                                 EraseRect(&sizeRect);
  164.                                 InvalRect(&sizeRect);
  165.                                 SizeWindow(twindow, back & 0xffff, back >> 16, true);
  166.                                 ((*tempWCH)->sizeMe)(twindow, fHit);
  167.                             }
  168.                         }
  169.                         InvalRect(&twindow->portRect);
  170.                         
  171.                         break;
  172.                     case inGoAway:
  173.                         /* Click in Close box */
  174.                         if (((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow) {
  175.                             if (TrackGoAway(twindow, myEventRecord.where))
  176.                                 ((*(windowCHandle)((WindowPeek)twindow)->refCon)->closeMe)(twindow);
  177.                         }
  178.                         break;
  179.                     case inZoomIn:
  180.                     case inZoomOut:
  181.                         if (TrackBox(twindow, myEventRecord.where, fHit)) {
  182.                             if (((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow) {
  183.                                 windowCHandle tempWCH = (windowCHandle)GetWRefCon(twindow);
  184.                                 SetPort(twindow);
  185.                                 
  186.                                 ZoomWindow(twindow, fHit, true);
  187.                                 InvalRect(&twindow->portRect);
  188.                                 ((*tempWCH)->sizeMe)(twindow, fHit);
  189.                             }
  190.                         }
  191.                 }
  192.             case mouseUp:
  193.                 /* don't care */
  194.                 break;
  195.                 /* same action for key or auto key */
  196.             case keyDown:
  197.             case autoKey:
  198.                 if (myEventRecord.modifiers & cmdKey)
  199.                     DoSelected(MenuKey(myEventRecord.message & charCodeMask));
  200.                 break;
  201.             case keyUp:
  202.                 /* don't care */
  203.                 break;
  204.             case diskEvt:
  205.                 /* I don't do anything special for disk events, this just passes them */
  206.                 /* to a function that checks for an error on the mount */
  207.                 DoDiskEvents(myEventRecord.message);
  208.                 break;
  209.             case activateEvt:
  210.                 if (myEventRecord.modifiers & activeFlag &&
  211.                     ((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow) {
  212.                     tempWCH = (windowCHandle)GetWRefCon((WindowPtr)myEventRecord.message);
  213.                     ((*tempWCH)->drawMe)((WindowPtr)myEventRecord.message);
  214.                 }
  215.                 break;
  216.             case 10:
  217.                 /* don't care */
  218.                 break;
  219.             case 11:
  220.                 /* don't care */
  221.                 break;
  222.             case 15:
  223.                 switch ((myEventRecord.message >> 24) & 0x0FF) {        /* high byte of message */
  224.                     case suspendResumeMessage:              /* suspend/resume is also an activate/deactivate */
  225.                         gInBackground = (myEventRecord.message & kResumeMask) == 0;
  226.                         if (!gInBackground) {
  227.                             
  228.                         }
  229.                         break;
  230.                 }
  231.                 break;
  232.             default:
  233.                 break;
  234.                 /* This dispatches high level events (AppleEvents, for example) */
  235.                 /* to our dispatch routine.  This is NEW in the event loop for */
  236.                 /* System 7 */
  237.             case kHighLevelEvent:
  238.                 DoHighLevel(&myEventRecord);
  239.                 break;
  240.                 
  241.         }
  242.     }
  243.             while (gQuit != true);
  244.     
  245. }
  246.  
  247. /* DoDaCall opens the requested DA.  It's here as a seperate routine if you'd */
  248. /* like to perform some action or just know when a DA is opened in your */
  249. /* layer.  Can be handy to track memory problems when a DA is opened */
  250. /* with an Option-open */
  251. void DoDaCall(MenuHandle themenu, long theit)
  252. {
  253.     long qq;
  254.     Str255 DAname;
  255.     GetMenuItemText(themenu, theit, DAname);
  256.     qq = OpenDeskAcc(DAname);
  257. }
  258.  
  259. /* end DoDaCall */
  260.  
  261. /* DoDiskEvents just checks the error code from the disk mount, */
  262. /* and puts up the 'Format' dialog (through DIBadMount) if need be */
  263. /* You can do much more here if you care about what disks are */
  264. /* in the drive */
  265. void DoDiskEvents(long dinfo)                               /* hi word is error code, lo word is drive number */
  266. {
  267.     short hival, loval, tommy;
  268.     Point fredpoint =  {
  269.         40, 40
  270.     };
  271.     hival = HiWord(dinfo);
  272.     loval = LoWord(dinfo);
  273.     if (hival != noErr)                                     /* something happened */ {
  274.         tommy = DIBadMount(fredpoint, dinfo);
  275.     }
  276. }
  277.  
  278. /* draws my window.  Pretty simple */
  279. void DrawMain(WindowPtr drawIt)
  280. {
  281.     RgnHandle tempRgn;
  282.     Rect scratchRect;
  283.     BeginUpdate(drawIt);
  284.     SetPort(drawIt);
  285.     MoveTo(20,20);
  286.     DrawString("\p Select NoResDialog from the Test Stuff menu");
  287.     scratchRect = drawIt->portRect;
  288.     scratchRect.top = scratchRect.bottom - 15;
  289.     scratchRect.left = scratchRect.right - 15;
  290.     tempRgn = NewRgn();
  291.     GetClip(tempRgn);
  292.     ClipRect(&scratchRect);
  293.     DrawGrowIcon(drawIt);
  294.     SetClip(tempRgn);
  295.     DisposeRgn(tempRgn);
  296.     
  297.     EndUpdate(drawIt);
  298. }
  299.  
  300. /* my menu action taker.  It returns a Boolean which I usually ignore, but it */
  301. /* mught be handy someday */
  302. /* I usually use it in an application to determine if a keystroke was accepted */
  303. /* by a menu or whether it should be passed along to any other key acceptors */
  304. Boolean DoSelected(long val)
  305. {
  306.     short loval, hival;
  307.     Boolean returnVal = false;
  308.     loval = LoWord(val);
  309.     hival = HiWord(val);
  310.     
  311.     switch (hival) {                                        /* switch off the menu number selected */
  312.         case kAppleMenu:                                    /* Apple menu */
  313.             if (loval != 1) {                               /* if this was not About, it's a DA */
  314.                 DoDaCall(GetMenuHandle(kAppleMenu), loval);
  315.             } else {
  316.                 Alert(kAboutBox, nil);                      /* do about box */
  317.             }
  318.             returnVal = true;
  319.             break;
  320.         case kFileMenu:                                     /* File menu */
  321.             switch (loval) {
  322.                 case kQuitItem:
  323.                     gQuit = true;                           /* only  item */
  324.                     returnVal = true;
  325.                     break;
  326.                 default:
  327.                     break;
  328.             }
  329.             break;
  330.         case kEditMenu:
  331.             /* edit menu junk */
  332.             /* don't care */
  333.             switch (loval) {
  334.             default:
  335.                 break;
  336.             }
  337.             break;
  338.         case kToolsMenu:
  339.             /* add all your test stuff here */
  340.             NoResDialog();
  341.             switch (loval) {
  342.             default:
  343.                 break;
  344.             }
  345.             break;
  346.         case kHMHelpMenuID:                                 /* Defined in Balloons.h */
  347.             /* I only care about this item.  If anything else is returned here, I don't know what */
  348.             /* it is, so I leave it alone.  Remember, the Help Manager chapter says that */
  349.             /* Apple reserves the right to add and change things in the Help menu */
  350.             if (loval == gHelpItem)
  351.                 SampleHelpDialog();
  352.             break;
  353.             
  354.     }
  355.     HiliteMenu(0);
  356.     return(returnVal);
  357. }
  358.  
  359. void DoDocumentClick(WindowPtr theWindow, EventRecord *theEvent)
  360. {
  361. #pragma unused ( theWindow,theEvent)    
  362. }
  363.  
  364. /* InitAEStuff installs my appleevent handlers */
  365. void InitAEStuff(void)
  366. {
  367.     AEinstalls HandlersToInstall[] =  {
  368.         {
  369.             kCoreEventClass, kAEOpenApplication, AEOpenHandler
  370.         },  {
  371.             kCoreEventClass, kAEOpenDocuments, AEOpenDocHandler
  372.         },  {
  373.             kCoreEventClass, kAEQuitApplication, AEQuitHandler
  374.         },  {
  375.             kCoreEventClass, kAEPrintDocuments, AEPrintHandler
  376.         }, 
  377.         /* The above are the four required AppleEvents. */
  378.         
  379.     };
  380.     
  381.     OSErr aevtErr = noErr;
  382.     long aLong = 0;
  383.     Boolean gHasAppleEvents = false;
  384.     /* Check this machine for AppleEvents.  If they are not here (ie not 7.0)
  385.     *   then we exit */
  386.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &aLong) == noErr);
  387.     /* The following series of calls installs all our AppleEvent Handlers.
  388.     *   These handlers are added to the application event handler list that 
  389.     *   the AppleEvent manager maintains.  So, whenever an AppleEvent happens
  390.     *   and we call AEProcessEvent, the AppleEvent manager will check our
  391.     *   list of handlers and dispatch to it if there is one.
  392.     */
  393.     if (gHasAppleEvents) {
  394.         register qq;
  395.         for (qq = 0; qq < ((sizeof(HandlersToInstall) / sizeof(AEinstalls))); qq++) {
  396.             aevtErr = AEInstallEventHandler(HandlersToInstall[qq].theClass, HandlersToInstall[qq].theEvent,
  397.                                             NewAEEventHandlerProc(HandlersToInstall[qq].theProc), 0, false);
  398.             if (aevtErr) {
  399.                 ExitToShell();                              /* just fail, baby */
  400.             }
  401.         }
  402.     } else {
  403.         ExitToShell();
  404.     }
  405. }
  406.  
  407. /* end InitAEStuff */
  408. /* I'm not doing error handling in this sample for clarities sake, you should. Hah, */
  409. /* easy for me to say, huh? */
  410. void DoHighLevel(EventRecord *AERecord)
  411. {
  412.     OSErr myErr;
  413.     myErr = AEProcessAppleEvent(AERecord);
  414.     
  415. }
  416.  
  417. /* end DoHighLevel */
  418.  
  419. /* This is the standard Open Application event.  */
  420. pascal OSErr AEOpenHandler(const AppleEvent *messagein, AppleEvent *reply, unsigned long refIn)
  421. {
  422.     WindowPtr myWindow;
  423.  
  424. #pragma unused (messagein,reply,refIn)
  425.     /* we of course don't do anything here in this simple app */
  426.     /* except open our window */
  427.     myWindow = AddNewWindow(kDocWindowResID);
  428.     
  429.     return(noErr);
  430. }
  431.  
  432. /* end AEOpenHandler */
  433.  
  434. /* Open Doc, opens our documents.  Remember, this can happen at application start AND */
  435. /* anytime else.  If your app is up and running and the user goes to the desktop, hilites one */
  436. /* of your files, and double-clicks or selects Open from the finder File menu this event */
  437. /* handler will get called. Which means you don't do any initialization of globals here, or */
  438. /* anything else except open then doc.  */
  439. /* SO-- Do NOT assume that you are at app start time in this */
  440. /* routine, or bad things will surely happen to you. */
  441.  
  442. pascal OSErr AEOpenDocHandler(const AppleEvent *messagein, AppleEvent *reply, unsigned long refIn)
  443. {
  444. #pragma unused (messagein,refIn,reply)
  445.     /* we of course don't do anything here */
  446.     return(errAEEventNotHandled);                           /* we have no docs, so no odoc events should come to us */
  447. }
  448.  
  449. pascal OSErr AEPrintHandler(const AppleEvent *messagein, AppleEvent *reply, unsigned long refIn)
  450. {                                                           /* no printing handler in yet, so we'll ignore this */
  451.     /* the operation is functionally identical to the ODOC event, with the additon */
  452.     /* of calling your print routine.  */
  453. #pragma unused (messagein,refIn,reply)
  454.     /* we of course don't do anything here */
  455.     return(errAEEventNotHandled);                           /* we have no docs, so no pdoc events should come to us */
  456. }
  457.  
  458. /* Standard Quit event handler, to handle a Quit event from the Finder, for example.  */
  459. /* ••••• DO NOT CALL EXITTOSHELL HERE ••••• or you will never have a happy life.  */
  460. /* OK, it's a few months after I wrote that comment, and I've seen a lot of code */
  461. /* come through DTS that calls ExitToShell from quit handlers.  Let me explain... */
  462. /* When an AppleEvent Handler is called (like this quit handler) you are ALMOST */
  463. /* 100% in your application world.  A5 is right, you can call any toolbox function, */
  464. /* you can call your own routines, everything _seems_ like you are in complete  */
  465. /* control.  Well, almost but not quite.  The routine has been dispatch to from the */
  466. /* AppleEvent Manager's space, so you _must_ return to that at some point! */
  467. /* Which is why you can't call ETS from here.  When you call ExitToShell from an */
  468. /* AE Handler, the most likely thing that happens is the FInder quits, and your  */
  469. /* application keeps running.  Which ain't what you want, y'know? */
  470. /* so, DON'T CALL EXITTOSHELL FROM AN APPLEEVENT HANDLER!!!!!!!!!!!!!! */
  471. pascal OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, unsigned long refIn)
  472. {
  473. #pragma unused (messagein,refIn,reply)
  474.     gQuit = true;
  475.     return(noErr);
  476. }
  477.  
  478.  
  479. /* This is my sample help dialog.  Does not do anything, expand as you need */
  480. void SampleHelpDialog(void)
  481. {
  482.     DialogPtr tdial = GetNewDialog(kSampHelp, nil, (WindowPtr)-1);
  483.     short itemhit = 0;
  484.     while (itemhit != 1) {
  485.         ModalDialog(nil, &itemhit);
  486.     }
  487.     DisposeDialog(tdial);
  488. }
  489.  
  490.  
  491. #pragma segment Initialize
  492. void InitalizeApp(void)
  493. {
  494.     Handle myMenu;
  495.     MenuHandle helpHandle, appleMenuHandle;
  496.     StringHandle helpString;
  497.     short count;
  498.     long vers;
  499.  
  500.     MaxApplZone();
  501.     InitGraf((Ptr)&qd.thePort);
  502.     InitFonts();
  503.     InitWindows();
  504.     InitMenus();
  505.     TEInit();
  506.     InitDialogs(nil);
  507.     InitCursor();
  508.     /* Check system version */
  509.     Gestalt(gestaltSystemVersion, &vers);
  510.     vers = (vers >> 8) & 0xf;                               /* shift result over and mask out major version number */
  511.     if (vers < 7) {
  512.         StopAlert(kBadSystem, nil);
  513.         ExitToShell();
  514.     }
  515.     InitAEStuff();
  516.     /* set up my menu junk */
  517.     myMenu = GetNewMBar(kMBarID);
  518.     SetMenuBar(myMenu);
  519.     appleMenuHandle = GetMenuHandle(kAppleMenu);
  520.     AppendResMenu(appleMenuHandle, 'DRVR');
  521.     /* now install my Help menu item in the Help Manager's menu */
  522.     HMGetHelpMenuHandle(&helpHandle);                       /* Get the Hlpe menu handle */
  523.     count = CountMItems(helpHandle);                        /* How many items are there? */
  524.     helpString = GetString(kHelpString);                    /* get my help string */
  525.     DetachResource((Handle)helpString);                             /* detach it */
  526.     HNoPurge((Handle)helpString);
  527.     MoveHHi((Handle)helpString);
  528.     HLock((Handle)helpString);
  529.     InsertMenuItem(helpHandle, (ConstStr255Param)helpString, count + 1);       /* insert my item in the Help menu */
  530.     gHelpItem = CountMItems(helpHandle);                    /* The number of the item */
  531.     
  532.     InsertMenu(GetMenu(90), -1);
  533.     DrawMenuBar();
  534.     GetCurrentProcess(&gOurSN);                             /* Get our process serial number for later use, if needed */
  535.     
  536. }
  537.  
  538.  
  539. #pragma segment Main
  540. WindowPtr AddNewWindow(short theID)
  541. {
  542.     windowCHandle setControls;
  543.     WindowPtr tempWP;
  544.     short cnt = 0;
  545.     tempWP = GetNewWindow(theID, 0, (WindowPtr)-1);         /* get a new window */
  546.     ((WindowPeek)tempWP)->windowKind = kMyDocumentWindow;       /* mark it as my document window */
  547.     setControls = (windowCHandle)NewHandleClear(sizeof(windowControl));     /* add our control structure to it */
  548.     SetWRefCon(tempWP, (long)setControls);                  /* stop stuffing refCon directly <ckh 1.0.3> */
  549.     HLock((Handle)setControls);                             /* lock it down while we fill it*/
  550.     
  551.     /* add pointers to our procedures for drawing, saving, and closing */
  552.     /* This way, all I need is one dispatch point for drawing, closing */
  553.     /* or whatever, I don't have to case off the window kind to go to the  */
  554.     /* correct routine.  Kinda like object-oriented programming, but I won't */
  555.     /* admit that. */
  556.     (*setControls)->drawMe = DrawMain;
  557.     (*setControls)->clickMe = DoDocumentClick;
  558.     (*setControls)->sizeMe = SizeMain;
  559.     (*setControls)->generalData = NewHandle(0);
  560.     return(tempWP);
  561. }
  562.  
  563. void SizeMain(WindowPtr theWindow, short how)
  564. {
  565. #pragma unused (how )
  566.     WindowPtr tempWP;
  567.     GetPort(&tempWP);
  568.     InvalRect(&theWindow->portRect);
  569.     SetPort(tempWP);
  570. }
  571.  
  572. void NilProc(void)
  573. {
  574.     
  575. }
  576.  
  577. /* This is a structure I defined to make it easier for me to add a new */
  578. /* dialog item to a DITL  */
  579. /* The definition of this comes from Inside Mac volume I, page 427 */
  580. /* or Inside Mac: Mac Toolbox  Essentials page 6-153 */
  581. typedef struct ditlItemTemplate {
  582.     long placeHolder;
  583.     Rect boundsRect;
  584.     Byte itemType;
  585.     Byte followingCount;
  586. } ditlItemTemplate;
  587.  
  588. /* My function for creating a DITL, creating a dialog, and running the dialog */
  589. /* without using resources */
  590. void NoResDialog(void)
  591. {
  592.  
  593. DialogPtr myDialog;
  594. short hitItem = 0;
  595.  
  596. /* rectangle for our dialog */
  597. Rect theBounds =  { 40, 40, 250, 300};
  598.  
  599. /* rectangles for our two dialog items */
  600.  
  601. Rect theOKRect =  { 100, 100, 120, 160 };
  602.  
  603. Rect thenotOKRect =  {130, 100, 150, 160  };
  604.  
  605.  
  606.     Rect tempRect;                                          /* these  three are here for all the GetDItem/SetDItem calls*/
  607.     short tempItem;
  608.     Handle tempHandle;
  609.  
  610. /* An empty handle that we will build our dialog item list (DITL) in */
  611. Handle ditlList = NewHandle(0);
  612.  
  613. /* scratch variables */
  614. Size currentSize;
  615. Size stringCount;
  616. Str15 theOKword = "\pOK";
  617. short *theDPtr;
  618.  
  619. /* The item template (based on our structure above) that we'll use to create our DITL */
  620. ditlItemTemplate currentItem;
  621.  
  622.  
  623. /* add an OK button to the dialog by hand-building  */
  624. /* a DITL */
  625.  
  626. /* first add the count of items that will be in the DITL */
  627. SetHandleSize(ditlList, 2);
  628. theDPtr = (short *)*ditlList;
  629.  
  630. /* I'm creating a two item list, one for the OK button, the other for the Not OK button */
  631. *theDPtr = 1;
  632.  
  633. /* Set up our first item, the OK button */
  634. currentItem.placeHolder = 0;                            /* always 0 */
  635. currentItem.boundsRect = theOKRect;                     /* rectangle to use */
  636. currentItem.itemType = ctrlItem;                        /* what type of item it is, it's a button */
  637. currentItem.followingCount = theOKword[0];              /* how long the button title is in bytes */
  638.  
  639. /* get the current size of the item list, and append this item definition to the handle */
  640. currentSize = GetHandleSize(ditlList);
  641. SetHandleSize(ditlList, currentSize + sizeof(currentItem));
  642. BlockMove((Ptr)¤tItem, (Ptr)(*ditlList + currentSize), sizeof(currentItem));
  643.  
  644. /* now move the text of the OK word into the handle */
  645. /* NOTE:  It's got to be even, so if the string is odd */
  646. /* I'll actually move one more byte than is there */
  647.  
  648. /* Obviosly I know what it is in this case, I'm just doing this so you'll see */
  649. /* what would need to be done in the generic case */
  650.  
  651. stringCount = theOKword[0];
  652. if (stringCount & 0x1)   /* if odd */
  653.     stringCount++;        /* make even */
  654. currentSize = GetHandleSize(ditlList);
  655. SetHandleSize(ditlList, currentSize + stringCount);    
  656. BlockMove((Ptr)&theOKword[1], (Ptr)(*ditlList + currentSize), stringCount);
  657.  
  658. /* Now add another button, the Not OK button */
  659. currentItem.placeHolder = 0;                            
  660. currentItem.boundsRect = thenotOKRect;              
  661. currentItem.itemType = userItem;                      
  662. currentItem.followingCount =0;                   
  663.  
  664. /* get the current size of the item list, and append this item definition to the handle */
  665. currentSize = GetHandleSize(ditlList);
  666. SetHandleSize(ditlList, currentSize + sizeof(currentItem));
  667. BlockMove((Ptr)¤tItem, (Ptr)(*ditlList + currentSize), sizeof(currentItem));
  668.  
  669.  
  670. /* So, we've built a DITL.  Now we can create the dialog, since we have something to  */
  671. /* pass to it */
  672. /* we're creating it invisibly, since we have to add the drawing proc */
  673. /* for the user item after we create the dialog */
  674. myDialog = NewDialog(nil, &theBounds, nil, false, dBoxProc, (WindowPtr)-1, false, nil, ditlList);
  675.  
  676.             GetDialogItem(myDialog, 2, &tempItem, &tempHandle, &tempRect);
  677.             SetDialogItem(myDialog, 2, tempItem, (Handle)NewControlUserPaneDrawProc(BorderDefault), &tempRect);
  678. ShowWindow(myDialog);
  679. /* run it with ModalDialog! */
  680. do {
  681.     ModalDialog(nil, &hitItem);
  682. }
  683.         while (hitItem != 1);
  684. DisposeDialog(myDialog);
  685. // the Dialog manager has deleted the DITL handle for us
  686. }
  687.  
  688. /* BorderDefault draws a heavy border around the default button (in this case the OK button ) */
  689. /* Again, not necessary if the new DM calls are in */
  690. pascal void BorderDefault(DialogPtr dwind, short dinum)
  691. {
  692. #pragma unused (dinum)
  693.     short itemtype;
  694.     Handle itemhandle;
  695.     Rect borderRect;
  696.     GetDialogItem(dwind, ok, &itemtype, &itemhandle, &borderRect);
  697.     /* ok is defined as 1 in the interfaces.  If you'd like another item outlined, */
  698.     /* change this number, of course. */
  699.     InsetRect(&borderRect, -4, -4);
  700.     PenSize(3, 3);
  701.     FrameRoundRect(&borderRect, 16, 16);
  702.     PenSize(1, 1);
  703. } /* end BorderDefault */
  704.